package com.leyou.item.service.iml;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.QuerySpuByPageMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class QuerySpuByPageServieImpl extends ServiceImpl<QuerySpuByPageMapper, Spu> implements QuerySpuByPageServie {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuDetailService spuDetailService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private  ParamService paramService;

    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        //创建分页对象
        Page<Spu> queryPage = new Page<>(page, rows);
        //传入条件反填充queryPage  eq查询条件
        page(queryPage, new QueryWrapper<Spu>()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
        );
        //为SpuDTO完善条件
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(queryPage.getRecords());
        for (SpuDTO dto : spuDTOS) {
            //从spuDTO中获取brand的id并且获取name
            String name = this.brandService.getById(dto.getBrandId()).getName();
            dto.setBrandName(name);

            //获取种类的name
            String CategoryName = this.categoryService.listByIds(dto.getCategoryIds())
                    .stream()
                    .map(Category::getName)
                    .collect(Collectors.joining("/"));
            dto.setCategoryName(CategoryName);
        }
        return new PageDTO<>(queryPage.getTotal(), queryPage.getPages(), spuDTOS);
    }

    @Override
    public void addGoods(SpuDTO spuDTO) {
        //新增在三张表spu sku spudetail插入数据
        //spu插入
        Spu spu = spuDTO.toEntity(Spu.class);
        this.save(spu);

        //spudetail插入
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        this.spuDetailService.save(spuDetail);

        //sku插入
        List<Sku> skus = spuDTO.getSkus()
                .stream().map(skuDTO -> {
                    Sku sku = new Sku();
                    BeanUtils.copyProperties(skuDTO, sku);
                    return sku;
                }).collect(Collectors.toList());
        //批量插入
        skuService.saveBatch(skus);


    }

    //根据ID查询商品
    @Override
    public SpuDTO queryGoodsById(Long id) {
        SpuDTO spuDTO = querySpuByPage(1, 1, null, null, null, id).getItems().get(0);
        spuDTO.setSpuDetail(new SpuDetailDTO(this.spuDetailService.getById(id)));

        List<SkuDTO> spu_id = SkuDTO.convertEntityList(this.skuService.query().eq("spu_id", id).list());
        spuDTO.setSkus(spu_id);

        return spuDTO;
    }

    //修改商品
    @Override
    public void updateGoods(SpuDTO spuDTO) {
        //前端方法 三种情况表示不同的表spu,sku,spu_detail
        if (spuDTO.getId() != null) {
            //spu不为空表示内容有修改更新
            Spu spu = spuDTO.toEntity(Spu.class);
            spu.setCreateTime(new Date());
            this.updateById(spu);
        }
        //如果不为空则表示有修改spu_detail
        if (spuDTO.getSpuDetail() != null) {
            SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
            this.spuDetailService.updateById(spuDetail);
        }
        //sku
        if (spuDTO.getSkus() != null && spuDTO.getSkus().size() != 0) {

            //获取获取实体类skus
            List<Sku> skus = spuDTO.getSkus().stream().map(skuDTO -> {
                Sku sku = new Sku();
                BeanUtils.copyProperties(skuDTO, sku);
                return sku;
            }).collect(Collectors.toList());

            //分组处理 是否下架做分组 true表示不下架,新增或者修改 false表示下架表示为删除
            Map<Boolean, List<Sku>> skuMaps = skus.stream().collect(Collectors.groupingBy(sku -> {
                return sku.getSaleable() == null;
            }));
            //新增或者修改
            List<Sku> toUpdateOrSave = skuMaps.get(true);
            this.skuService.saveOrUpdateBatch(toUpdateOrSave);
            //删除
            List<Sku> toDelete = skuMaps.get(true);
            this.skuService.removeByIds(toDelete.stream().map(Sku::getId).collect(Collectors.toList()));

        }

    }

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        this.updateById(spu);

        Sku sku = new Sku();
        sku.setSpuId(id);
        sku.setSaleable(saleable);
        //update tb_sku set seleable=#{seleable} where spu_id=#{id}
        this.skuService.update(sku, new QueryWrapper<Sku>().eq("spu_id", id));
        String routingKey = saleable? "up" : "down";

        this.amqpTemplate.convertAndSend("jhj",routingKey,spu.getId());
    }


    @Override
    public List<SpecParamDTO> querySpecParamBySpu(Long id, Boolean searching) {
        Long categoryId = getById(id).getCid3();
        //根据条件（分类或者是否可搜索）查询规格参数
        List<SpecParamDTO> specParamDTOS = SpecParamDTO.convertEntityList(this.paramService.query()
                .eq("category_id", categoryId)
                .eq(null != searching, "searching", searching)
                .list());
        //把spuDetail中存储的规格参数的key：value信息取出备用
        //key==>specPramId,value===>当前商品此属性对应的value值
        Map<Long,Object> paramMap = JsonUtils.nativeRead(this.spuDetailService.getById(id).getSpecification(), new TypeReference<Map<Long, Object>>() {
        }) ;
        specParamDTOS.forEach(specParamDTO -> {

            Long specPramId = specParamDTO.getId();
            specParamDTO.setValue(paramMap.get(specPramId));

        });
        return specParamDTOS;
    }

}
